package com.project.school_flate.serviceimpl.delivery;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.project.school_flate.dto.delivery.DeliveryInfoDto;
import com.project.school_flate.entity.delivery.DeliveryInfo;
import com.project.school_flate.entity.delivery.table.DeliveryInfoTableDef;
import com.project.school_flate.entity.order.table.OrderDeliveryTableDef;
import com.project.school_flate.entity.order.table.OrderTakeawayTableDef;
import com.project.school_flate.entity.shop.ShopAccount;
import com.project.school_flate.entity.table.delivery.DeliveryInfoTable;
import com.project.school_flate.entity.table.shop.ShopAccountTable;
import com.project.school_flate.mapper.delivery.DeliveryExamineMapper;
import com.project.school_flate.mapper.delivery.DeliveryInfoMapper;
import com.project.school_flate.mapper.order.OrderDeliveryMapper;
import com.project.school_flate.mapper.order.OrderTakeawayMapper;
import com.project.school_flate.service.delivery.DeliveryInfoService;
import com.project.school_flate.util.HttpClientUtil;
import com.project.school_flate.util.Md5Util;
import com.project.school_flate.util.PoToDTO;
import com.project.school_flate.util.Result.Result;
import com.project.school_flate.util.system.ComVariableUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.ArrayList;
import java.util.List;

/**
 *  服务层实现。
 *
 * @author 马维健
 * @since 2024/1/2
 */
@Service
public class DeliveryInfoServiceImpl extends ServiceImpl<DeliveryInfoMapper, DeliveryInfo> implements DeliveryInfoService {

    @Autowired
    private DeliveryInfoMapper oDeliveryInfoMapper;

    @Autowired
    private DeliveryExamineMapper oDeliveryExamineMapper;

    @Autowired
    private OrderDeliveryMapper oOrderDeliveryMapper;

    // 微信公众号授权登录请求的网址
    public static final String WX_LOGIN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";

    /**
     * 获取配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    public Result getDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        List<DeliveryInfo> oDeliveryInfoList = new ArrayList<>();
        long total = 0;
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(DeliveryInfoTable.DELIVERY_INFO.STATE.eq(1));
        //判断是否传入配送员ID
        if(StringUtils.isNotBlank(oDeliveryInfoDto.getId())){
            queryWrapper.where(DeliveryInfoTable.DELIVERY_INFO.ID.eq(oDeliveryInfoDto.getId()));
        }
        queryWrapper.orderBy("create_time desc");
        //是否分页
        if(oDeliveryInfoDto.getPage() != null && oDeliveryInfoDto.getLimit() != null){
            Page<DeliveryInfo> DeliveryInfoPage = oDeliveryInfoMapper.paginateWithRelations(oDeliveryInfoDto.getPage(),oDeliveryInfoDto.getLimit(),queryWrapper);
            oDeliveryInfoList = DeliveryInfoPage.getRecords();
            total = DeliveryInfoPage.getTotalRow();
        }else{
            oDeliveryInfoList = oDeliveryInfoMapper.selectListWithRelationsByQuery(queryWrapper);
            total = oDeliveryInfoList.size();
        }
        //PoToDto
        List<DeliveryInfoDto> oDeliveryInfoDtoList = (List<DeliveryInfoDto>) PoToDTO.poToDtoList(oDeliveryInfoList,new DeliveryInfoDto());
        return Result.ok(oDeliveryInfoDtoList,total);
    }

    /**
     * 添加配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result addDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        PoToDTO.poToDto(oDeliveryInfoDto,oDeliveryInfo);
        if(oDeliveryInfoMapper.insert(oDeliveryInfo) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("添加配送员失败");
        }
        return Result.ok("添加配送员成功");
    }

    /**
     * 修改配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result updateDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        PoToDTO.poToDto(oDeliveryInfoDto,oDeliveryInfo);
        if(oDeliveryInfoMapper.update(oDeliveryInfo) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("修改配送员失败");
        }
        return Result.ok("修改配送员成功");
    }

    /**
     * 冻结配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result freezeDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        PoToDTO.poToDto(oDeliveryInfoDto,oDeliveryInfo);
        //判断配送员是否还有订单未完成
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(OrderDeliveryTableDef.ORDER_DELIVERY.DELIVERY_ID.eq(oDeliveryInfo.getId()));
        queryWrapper.where(OrderDeliveryTableDef.ORDER_DELIVERY.DELIVERY_STATE.ne(2));
        if(CollectionUtils.isNotEmpty(oOrderDeliveryMapper.selectListByQuery(queryWrapper))){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("配送员还有未完成的订单");
        }
        oDeliveryInfo.setState(0);
        if(oDeliveryInfoMapper.update(oDeliveryInfo) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("冻结配送员失败");
        }
        return Result.ok("冻结配送员成功");
    }

    /**
     * 获取配送员（后台）
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    public Result getDeliveryInfoBack(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        List<DeliveryInfo> oDeliveryInfoList = new ArrayList<>();
        long total = 0;
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.orderBy("create_time desc");
        //是否分页
        if(oDeliveryInfoDto.getPage() != null && oDeliveryInfoDto.getLimit() != null){
            Page<DeliveryInfo> DeliveryInfoPage = oDeliveryInfoMapper.paginateWithRelations(oDeliveryInfoDto.getPage(),oDeliveryInfoDto.getLimit(),queryWrapper);
            oDeliveryInfoList = DeliveryInfoPage.getRecords();
            total = DeliveryInfoPage.getTotalRow();
        }else{
            oDeliveryInfoList = oDeliveryInfoMapper.selectListWithRelationsByQuery(queryWrapper);
            total = oDeliveryInfoList.size();
        }
        //PoToDto
        List<DeliveryInfoDto> oDeliveryInfoDtoList = (List<DeliveryInfoDto>) PoToDTO.poToDtoList(oDeliveryInfoList,new DeliveryInfoDto());
        return Result.ok(oDeliveryInfoDtoList,total);
    }

    /**
     * 解冻配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Transactional
    @Override
    public Result thawDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        PoToDTO.poToDto(oDeliveryInfoDto,oDeliveryInfo);
        oDeliveryInfo.setState(1);
        if(oDeliveryInfoMapper.update(oDeliveryInfo) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("解冻配送员失败");
        }
        return Result.ok("解冻配送员成功");
    }

    /**
     * 注册配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Transactional
    @Override
    public Result registerDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        PoToDTO.poToDto(oDeliveryInfoDto,oDeliveryInfo);
        //判断手机号是否存在
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(DeliveryInfoTable.DELIVERY_INFO.PHONE.eq(oDeliveryInfo.getPhone()));
        if(oDeliveryInfoMapper.selectOneByQuery(queryWrapper) != null){
            return Result.error("手机号已存在，请前往登录");
        }
        //判断openId是否存在
        queryWrapper = new QueryWrapper();
        queryWrapper.where(DeliveryInfoTable.DELIVERY_INFO.WX_OPTION_ID.eq(oDeliveryInfo.getWxOptionId()));
        DeliveryInfo openDeliveryInfo = oDeliveryInfoMapper.selectOneByQuery(queryWrapper);
        if(StringUtils.isNotBlank(openDeliveryInfo.getPhone())){
            return Result.error("微信号已存在，请前往登录");
        }
        openDeliveryInfo.setPhone(oDeliveryInfo.getPhone());
        openDeliveryInfo.setPassword(Md5Util.code(oDeliveryInfo.getPassword()));
        if(oDeliveryInfoMapper.update(openDeliveryInfo) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("注册配送员失败");
        }
        return Result.ok("注册配送员成功");
    }

    public static void main(String[] args) {
        System.out.println(Md5Util.code("e10adc3949ba59abbe56e057f20f883e"));
    }

    /**
     * 登录配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result loginDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        PoToDTO.poToDto(oDeliveryInfoDto,oDeliveryInfo);
        //判断手机号是否存在
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(DeliveryInfoTable.DELIVERY_INFO.PHONE.eq(oDeliveryInfo.getPhone()));
        DeliveryInfo oldDeliveryInfo = oDeliveryInfoMapper.selectOneByQuery(queryWrapper);
        if(oldDeliveryInfo == null){
            return Result.error("手机号不存在");
        }
        //判断密码是否正确
        if(!oldDeliveryInfo.getPassword().equals(Md5Util.code(oDeliveryInfo.getPassword()))){
            return Result.error("密码错误");
        }
        //判断openId是否一样
        if(!oldDeliveryInfo.getWxOptionId().equals(oDeliveryInfo.getWxOptionId())){
            return Result.error("此微信绑定的不是当前手机号");
        }
        //PoToDto
        DeliveryInfoDto deliveryInfoDto = new DeliveryInfoDto();
        PoToDTO.poToDto(oldDeliveryInfo,deliveryInfoDto);
        deliveryInfoDto.setPassword("******");
        //用户登录
        StpUtil.login(deliveryInfoDto.getId());
        //登录缓存登录对象
        StpUtil.getSession().set("deliveryInfo", deliveryInfoDto);
        deliveryInfoDto.setToken(StpUtil.getTokenValue());
        return Result.ok(deliveryInfoDto);
    }

    /**
     * 退出配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    public Result exitDeliveryInfo(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        //获取当前配送员
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        if(StpUtil.isLogin()){
            oDeliveryInfo = (DeliveryInfo) StpUtil.getSession().get("deliveryInfo");
            if(oDeliveryInfo == null || StringUtils.isBlank(oDeliveryInfo.getId())){
                return Result.fail("当前登陆人失效");
            }
        }else{
            return Result.fail("当前登陆人失效");
        }
        StpUtil.logout(oDeliveryInfo.getId());
        return Result.ok();
    }

    /**
     * 配送员修改密码
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Transactional
    @Override
    public Result updateDeliveryInfoPassword(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfo oDeliveryInfo = new DeliveryInfo();
        PoToDTO.poToDto(oDeliveryInfoDto,oDeliveryInfo);
        //获取密码
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(DeliveryInfoTableDef.DELIVERY_INFO.ID.eq(oDeliveryInfo.getId()));
        queryWrapper.where(DeliveryInfoTableDef.DELIVERY_INFO.STATE.eq(1));
        DeliveryInfo oldDeliveryInfo = oDeliveryInfoMapper.selectOneByQuery(queryWrapper);
        if(oldDeliveryInfo == null){
            return Result.error("配送员不存在");
        }
        if(!oldDeliveryInfo.getPassword().equals(Md5Util.code(oDeliveryInfoDto.getOldPassword()))){
            return Result.error("原密码错误");
        }
        oDeliveryInfo.setPassword(Md5Util.code(oDeliveryInfo.getPassword()));
        if(oDeliveryInfoMapper.update(oDeliveryInfo) == 0){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Result.error("修改密码失败");
        }
        //退出登录
        StpUtil.logout(oDeliveryInfo.getId());
        return Result.ok("修改密码成功，请重新登录");
    }

    @Value("${loginTest}")
    private String loginTest;

    /**
     * 公众号登录配送员
     * @param oDeliveryInfoDto
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Result loginDeliveryInfoOfficial(DeliveryInfoDto oDeliveryInfoDto) throws Exception {
        DeliveryInfoDto deliveryInfoDto = new DeliveryInfoDto();
        if(Boolean.valueOf(loginTest)){
            DeliveryInfo oDeliveryInfo = oDeliveryInfoMapper.selectOneById("139537968155201536");
            PoToDTO.poToDto(oDeliveryInfo,deliveryInfoDto);
        }else{
            //需要拿客户端获得的code换取openId
            String url = String.format(WX_LOGIN_URL, ComVariableUtil.getSystemValue("wx_appid"), ComVariableUtil.getSystemValue("wx_secret"), oDeliveryInfoDto.getCode());
            //调用微信api授权
            String data = HttpClientUtil.doGet(url);
            //解析返回的json字符串
            JSONObject jsonObject = JSONObject.parseObject(data);
            //获取openid和token值
            String openId = jsonObject.getString("openid");
            String accessToken = jsonObject.getString("access_token");
            if (StringUtils.isEmpty(openId)) {
                return Result.fail("未获取到openId");
            }
            //通过openId获取配送员信息
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.where(DeliveryInfoTableDef.DELIVERY_INFO.WX_OPTION_ID.eq(openId));
            DeliveryInfo oldDeliveryInfo = oDeliveryInfoMapper.selectOneByQuery(queryWrapper);
            if(oldDeliveryInfo == null){
                // 通过openid 和 accessToken 来获取用户信息
                // 拼接请求地址
                String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
                requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
                //发送请求
                String urlRequest = HttpClientUtil.doGet(requestUrl);
                //解析返回的json字符串
                JSONObject userInfo = JSONObject.parseObject(urlRequest);
                //获取用户微信昵称和头像
                String nickname = userInfo.getString("nickname");
                String avatar = userInfo.getString("headimgurl");
                //新增配送员
                DeliveryInfo oDeliveryInfo = new DeliveryInfo();
                oDeliveryInfo.setName(nickname);
                oDeliveryInfo.setWxOptionId(openId);
                oDeliveryInfo.setImage(avatar);
                if(oDeliveryInfoMapper.insert(oDeliveryInfo) == 0){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return Result.error("配送员公众号登录失败");
                }
                PoToDTO.poToDto(oDeliveryInfo,deliveryInfoDto);
            }else{
                PoToDTO.poToDto(oldDeliveryInfo,deliveryInfoDto);
            }
        }
        return Result.ok(deliveryInfoDto);
    }

}
